#include <iostream>

#include "../../include/component_module.h"
#include "../../include/mutex_stub.h"

#define BOSS_TEST2_BEGIN_DECLARE_INTERFACE(iface_name, iface_uuid) \
  struct iface_name \
    : public Boss::IBase \
  { \
    BOSS_DECLARE_IFACE_UUID(iface_uuid)

#define BOSS_TEST2_END_DECLARE_INTERFACE() \
  };


BOSS_TEST2_BEGIN_DECLARE_INTERFACE(A, 1dbe998f-884b-449e-a1ec-4428ac2bbb66)
BOSS_TEST2_END_DECLARE_INTERFACE()

BOSS_TEST2_BEGIN_DECLARE_INTERFACE(B, 1a6c0707-24e5-470b-a2d8-036f61043ef6)
BOSS_TEST2_END_DECLARE_INTERFACE()

BOSS_TEST2_BEGIN_DECLARE_INTERFACE(C, c98156c9-4eab-4707-a6b4-ad2460d3deda)
BOSS_TEST2_END_DECLARE_INTERFACE()

BOSS_TEST2_BEGIN_DECLARE_INTERFACE(D, ca070b46-e66f-42ef-96ee-44da0d90c29f)
BOSS_TEST2_END_DECLARE_INTERFACE()

BOSS_TEST2_BEGIN_DECLARE_INTERFACE(E, 71d814cb-f93b-4f97-903a-a7b535b5b0ae)
BOSS_TEST2_END_DECLARE_INTERFACE()

BOSS_TEST2_BEGIN_DECLARE_INTERFACE(F, b68a6ff7-f3c2-43eb-af9e-cd84aa3401ca)
BOSS_TEST2_END_DECLARE_INTERFACE()


#define BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE() \
  bool FinalizeCreate() \
  { \
    std::cout << "FinalizeCreate [" << GetCoClassId() << "]" << std::endl; \

#define BOSS_TEST2_END_DECLARE_FINALIZE_CREATE() \
    return true; \
  }

#define BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(co_class_name, co_class_uuid, base_list) \
  class co_class_name \
    : public Boss::CoClassBase<base_list> \
  { \
  public: \
    BOSS_DECLARE_CLSID(co_class_uuid) \
    co_class_name() \
    { \
      std::cout << GetCoClassId() << std::endl; \
    } \
    ~co_class_name() \
    { \
      std::cout << "~ " << GetCoClassId() << std::endl; \
    }

#define BOSS_TEST2_END_DECLARE_CO_CLASS() \
    void BeforeDestroy() \
    { \
      std::cout << "BeforeDestroy [" << GetCoClassId() << "]" << std::endl; \
    } \
  };


typedef Boss::TL::TypeListAdapter<A> ABase;
BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(AImpl, 84da21f4-bbbc-4344-a5a6-92af1c378d58, ABase)
  BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE()
  BOSS_TEST2_END_DECLARE_FINALIZE_CREATE()
BOSS_TEST2_END_DECLARE_CO_CLASS()

typedef Boss::TL::TypeListAdapter<B> BBase;
BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(BImpl, e03e56da-1cba-4bef-a20f-22c9906bce07, BBase)
  BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE()
  BOSS_TEST2_END_DECLARE_FINALIZE_CREATE()
BOSS_TEST2_END_DECLARE_CO_CLASS()

typedef Boss::TL::TypeListAdapter<AImpl, BImpl, C> CBase;
BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(CImpl, 15660e34-3fab-4e0e-9cd4-135c213c3dda, CBase)
  BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE()
  BOSS_TEST2_END_DECLARE_FINALIZE_CREATE()
BOSS_TEST2_END_DECLARE_CO_CLASS()

typedef Boss::TL::TypeListAdapter<CImpl, D> DBase;
BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(DImpl, dcd7542c-0f26-4099-ac4a-775e3a762bec, DBase)
  BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE()
  BOSS_TEST2_END_DECLARE_FINALIZE_CREATE()
BOSS_TEST2_END_DECLARE_CO_CLASS()

typedef Boss::TL::TypeListAdapter<CImpl, E> EBase;
BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(EImpl, c854bcca-aa7c-47c3-9c36-2de0e6c1f950, EBase)
  BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE()
    std::cout << "\t: failed"<< std::endl;
    return false;
  BOSS_TEST2_END_DECLARE_FINALIZE_CREATE()
BOSS_TEST2_END_DECLARE_CO_CLASS()

typedef Boss::TL::TypeListAdapter<DImpl, EImpl, F> FBase;
BOSS_TEST2_BEGIN_DECLARE_CO_CLASS(FImpl, e8c3199e-2a82-4e7e-8279-ca90693ae5f0, FBase)
  BOSS_TEST2_BEGIN_DECLARE_FINALIZE_CREATE()
  BOSS_TEST2_END_DECLARE_FINALIZE_CREATE()
BOSS_TEST2_END_DECLARE_CO_CLASS()

BOSS_MODULE_INIT(Boss::MutexStub)

int main()
{
  try
  {
    Boss::IBaseImpl<FImpl>::Create();
  }
  catch (std::exception &e)
  {
    std::cerr << e.what() << std::endl;
  }
}
